package com.mazaiting.gateway.config;

import com.alibaba.fastjson.JSON;
import com.mazaiting.common.core.domain.result.Result;
import lombok.NonNull;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.web.reactive.error.ErrorWebExceptionHandler;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;
import org.springframework.core.io.buffer.DataBufferFactory;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.util.ObjectUtils;
import org.springframework.web.server.ResponseStatusException;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

/**
 * 全局异常配置
 */
@Slf4j
@Order(-1) // 保证优先级低于默认的ResponseStatusExceptionHandler,这样能拿到响应状态码
@Configuration
public class GlobalErrorExceptionConfig implements ErrorWebExceptionHandler {

    @Override
    @NonNull
    public Mono<Void> handle(ServerWebExchange exchange, @NonNull Throwable ex) {
        ServerHttpResponse response = exchange.getResponse();
        if (response.isCommitted()) {
            return Mono.error(ex);
        }
        // 将返回格式设为JSON
        response.getHeaders().setContentType(MediaType.APPLICATION_JSON);
        // 设置字符
        List<Charset> acceptCharsetList = new ArrayList<>();
        acceptCharsetList.add(StandardCharsets.UTF_8);
        response.getHeaders().setAcceptCharset(acceptCharsetList);
        // 设置响应状态码
        if (ex instanceof ResponseStatusException) {
            response.setStatusCode(((ResponseStatusException) ex).getStatus());
        }
        // 改变请求响应返回行为
        return response.writeWith(Mono.fromSupplier(() -> {
            DataBufferFactory bufferFactory = response.bufferFactory();
            ex.printStackTrace();
            log.info(ex.getMessage());
            // 服务不可用
            if (Objects.isNull(ex.getMessage()) || ex.getMessage().startsWith("Network is unreachable")) {
                response.setStatusCode(HttpStatus.INTERNAL_SERVER_ERROR);
            }
            // 响应码
            Integer code = ObjectUtils.isEmpty(response.getStatusCode()) ? 500 : response.getStatusCode().value();
            // 返回异常 1:  Network is unreachable: /192.168.161.152:9001
            Result<Object> result = Result.failed(code, ex.getMessage());
            // 返回ErrorResult
            return bufferFactory.wrap(JSON.toJSONString(result).getBytes());
        }));
    }
}